package com.umgsai.wx.backend.util;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.List;
import java.util.Map;

@Slf4j
public class JacksonUtil {

    public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    public static String toJSONString(Object object) {
        if (object == null) {
            return null;
        }
        if (object.getClass() == String.class) {
            return (String) object;
        }
        try {
            return OBJECT_MAPPER.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            log.error("JacksonUtil.toJSONString error:{}", object, e);
            return null;
        }
    }

    public static <T> T parseObject(String text, Class<T> tClass) {
        try {
            return OBJECT_MAPPER.readValue(text, tClass);
        } catch (IOException e) {
            log.error("JacksonUtil.parseObject error:{} {}", text, tClass.getName(), e);
            return null;
        }
    }

    public static <E> List<E> parseArray(String text, Class<E> tClass) {
        try {
            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, tClass));
        } catch (IOException e) {
            log.error("JacksonUtil.parseArray error:{} {}", text, tClass.getName(), e);
            return null;
        }
    }

    public static <K, V> Map<K, V> parseMap(String text, Class<K> kClass, Class<V> vClass) {
        try {
            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructMapType(Map.class, kClass, vClass));
        } catch (IOException e) {
            log.error("JacksonUtil.parseMap error:{} kClass:{} vClass:{}", text, kClass.getName(), vClass.getName(), e);
            return null;
        }
    }

    public static <T> T parseObject(String text, TypeReference<T> type) {
        try {
            return OBJECT_MAPPER.readValue(text, type);
        } catch (IOException e) {
            log.error("JacksonUtil.parseObject error:{} {}", text, type.getType().getTypeName(), e);
            return null;
        }
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    static class User {
        private Integer id;
        private String name;
        private Double age;
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    static class TestList {
        private List<Object> lives;
    }

    public static void main(String[] args) {
        User user = new User(1, "jack", 16.5);
        //序列化对象（转json）
        String json = toJSONString(user);
        System.out.println(json);
        System.out.println(JSON.toJSONString(user));

        //反序列化（json转为Bean）
        User user1 = parseObject(json, User.class);
        System.out.println(user1);
        System.out.println(JSON.parseObject(json, User.class));

        //反序列化（json转List）
        json = "[20, 15, -1, 22]";
        System.out.println(parseArray(json, String.class));
        System.out.println(parseArray(json, Integer.class));
        System.out.println(JSON.parseArray(json, Integer.class));
        System.out.println(JSON.parseArray(json, String.class));

        //反序列化（json转Map）
        json = "{\"name\" : \"历史\", \"id\":123, \"age\":12.2}";
        Map<String, Object> map = parseMap(json, String.class, Object.class);
        System.out.println(map);

        String text = "{\"status\": \"1\",\"count\": \"1\",\"info\": \"OK\",\"infoCode\": \"10000\",\"lives\": [{\"province\": \"河北\",\"city\": \"张家口市\",\"adCode\": \"130700\",\"weather\": \"晴\",\"temperature\": \"15\",\"winddirection\": \"西南\",\"windpower\": \"≤3\",\"humidity\": \"11\",\"reporttime\": \"2019-04-14 11:20:08\"}]}";
        Map<String, Object> stringObjectMap = parseMap(text, String.class, Object.class);
        System.out.println(stringObjectMap);

        TestList testList = parseObject(text, TestList.class);
        System.out.println(testList);


        //json转复杂对象
        json = "[{\"name\":\"李四\", \"age\":12.3}, {\"name\":\"王文\", \"age\":16.3}]";
        List<Map<String, String>> maps = parseObject(json, new TypeReference<List<Map<String, String>>>() {
        });
        System.out.println(maps);

        List<User> userList = parseObject(json, new TypeReference<List<User>>() {
        });
        System.out.println(userList);

        System.err.println(toJSONString(null));

        json = "{\"name\":\"李四\", \"age\":12.3}";
        User user2 = parseObject(json, new TypeReference<User>() {
        });
        System.out.println(user2);
    }
}
